<script setup lang="ts">
import { ref, computed, onMounted } from 'vue'
import { Clipboard, RefreshCw, Volume2, Code, Key, TowerControl } from 'lucide-vue-next'

// 摩斯密码映射表
const morseCodeMap = {
  'A': '.-', 'B': '-...', 'C': '-.-.', 'D': '-..', 'E': '.', 'F': '..-.',
  'G': '--.', 'H': '....', 'I': '..', 'J': '.---', 'K': '-.-', 'L': '.-..',
  'M': '--', 'N': '-.', 'O': '---', 'P': '.--.', 'Q': '--.-', 'R': '.-.',
  'S': '...', 'T': '-', 'U': '..-', 'V': '...-', 'W': '.--', 'X': '-..-',
  'Y': '-.--', 'Z': '--..',
  '0': '-----', '1': '.----', '2': '..---', '3': '...--', '4': '....-',
  '5': '.....', '6': '-....', '7': '--...', '8': '---..', '9': '----.',
  '.': '.-.-.-', ',': '--..--', '?': '..--..', "'": '.----.', '!': '-.-.--',
  '/': '-..-.', '(': '-.--.', ')': '-.--.-', '&': '.-...', ':': '---...',
  ';': '-.-.-.', '=': '-...-', '+': '.-.-.', '-': '-....-', '_': '..--.-',
  '"': '.-..-.', '$': '...-..-', '@': '.--.-.', ' ': '/'
}

// 反转映射表用于摩斯密码转文本
const reverseMorseMap: Record<string, string> = {}
Object.entries(morseCodeMap).forEach(([key, value]) => {
  reverseMorseMap[value] = key
})

// 响应式数据
const inputText = ref('')
const inputMorse = ref('')
const morseResult = ref('')
const textResult = ref('')
const isSignalActive = ref(false)
const showNotification = ref(false)
const notificationMessage = ref('')

// 创建摩斯密码表用于显示
const morseTable = computed(() => {
  const entries = Object.entries(morseCodeMap)
  const tableRows = []
  const itemsPerRow = 6 
  
  for (let i = 0; i < entries.length; i += itemsPerRow) {
    const row = []
    for (let j = 0; j < itemsPerRow; j++) {
      if (i + j < entries.length) {
        const [char, code] = entries[i + j]
        row.push({ char, code })
      }
    }
    tableRows.push(row)
  }
  
  return tableRows
})

// 文本转摩斯密码
const textToMorse = () => {
  if (!inputText.value.trim()) {
    morseResult.value = ''
    return
  }
  
  const text = inputText.value.toUpperCase()
  let result = ''
  
  for (let i = 0; i < text.length; i++) {
    const char = text[i]
    if (morseCodeMap[char as keyof typeof morseCodeMap]) {
      result += morseCodeMap[char as keyof typeof morseCodeMap] + ' '
    } else {
      result += char + ' '
    }
  }
  
  morseResult.value = result.trim()
}

// 摩斯密码转文本
const morseToText = () => {
  if (!inputMorse.value.trim()) {
    textResult.value = ''
    return
  }
  
  const morseWords = inputMorse.value.trim().split(' ')
  let result = ''
  
  for (const morseChar of morseWords) {
    if (morseChar === '/') {
      result += ' '
    } else if (reverseMorseMap[morseChar]) {
      result += reverseMorseMap[morseChar]
    } else {
      result += morseChar
    }
  }
  
  textResult.value = result
}

// 播放摩斯密码信号
const playMorse = () => {
  if (!morseResult.value) {
    showNotificationMessage('没有可播放的摩斯密码')
    return
  }
  
  const morse = morseResult.value
  let index = 0
  
  const playNext = () => {
    if (index >= morse.length) {
      isSignalActive.value = false
      return
    }
    
    const char = morse[index]
    isSignalActive.value = true
    
    let duration = 0
    
    if (char === '.') {
      duration = 200 // 短音
    } else if (char === '-') {
      duration = 600 // 长音
    } else if (char === ' ') {
      duration = 300 // 字符间隔
      isSignalActive.value = false
    } else if (char === '/') {
      duration = 700 // 单词间隔
      isSignalActive.value = false
    }
    
    setTimeout(() => {
      isSignalActive.value = false
      index++
      
      // 添加字符间隔
      setTimeout(playNext, 100)
    }, duration)
  }
  
  playNext()
}

// 复制结果
const copyResult = (text: string) => {
  if (!text) {
    showNotificationMessage('没有内容可复制')
    return
  }
  
  navigator.clipboard.writeText(text)
    .then(() => {
      showNotificationMessage('已复制到剪贴板！')
    })
    .catch(err => {
      console.error('复制失败:', err)
      showNotificationMessage('复制失败，请手动复制')
    })
}

// 显示通知
const showNotificationMessage = (message: string) => {
  notificationMessage.value = message
  showNotification.value = true
  
  setTimeout(() => {
    showNotification.value = false
  }, 2000)
}

// 清除输入
const clearInput = () => {
  inputText.value = ''
  inputMorse.value = ''
  morseResult.value = ''
  textResult.value = ''
}

// 组件初始化
onMounted(() => {
  inputText.value = 'HELLO WORLD'
  textToMorse()
})
</script>

<template>
  <div class="morse-container">
    <h1 class="title">
      <TowerControl class="icon" /> 摩斯密码转换器
    </h1>
    <p class="subtitle">双向转换工具 - 支持文本和摩斯密码互转</p>

    <div class="converter-grid">
      <!-- 文本转摩斯密码 -->
      <div class="converter-card">
        <h2 class="card-title">
          <Key class="icon" /> 文本转摩斯密码
        </h2>
        
        <div class="form-group">
          <textarea 
            v-model="inputText" 
            placeholder="在此输入文本（字母、数字、标点）..."
            @input="textToMorse"
            rows="5"
          ></textarea>
        </div>
        
        <div class="btn-group">
          <button class="btn primary" @click="textToMorse">
            <RefreshCw class="icon" /> 转换
          </button>
          <button 
            class="btn secondary" 
            @click="copyResult(morseResult)"
            :disabled="!morseResult"
          >
            <Clipboard class="icon" /> 复制结果
          </button>
          <button class="btn tertiary" @click="clearInput">
            <span>清除</span>
          </button>
        </div>
        
        <div class="result-box">
          <h3>摩斯密码结果：</h3>
          <div class="result-content">{{ morseResult || '-' }}</div>
        </div>
      </div>
      
      <!-- 摩斯密码转文本 -->
      <div class="converter-card">
        <h2 class="card-title">
          <Code class="icon" /> 摩斯密码转文本
        </h2>
        
        <div class="form-group">
          <textarea 
            v-model="inputMorse" 
            placeholder="在此输入摩斯密码（使用 . 和 -，字母间用空格分隔）..."
            @input="morseToText"
            rows="5"
          ></textarea>
        </div>
        
        <div class="btn-group">
          <button class="btn primary" @click="morseToText">
            <RefreshCw class="icon" /> 转换
          </button>
          <button 
            class="btn secondary" 
            @click="copyResult(textResult)"
            :disabled="!textResult"
          >
            <Clipboard class="icon" /> 复制结果
          </button>
          <button class="btn tertiary" @click="clearInput">
            <span>清除</span>
          </button>
        </div>
        
        <div class="result-box">
          <h3>文本结果：</h3>
          <div class="result-content">{{ textResult || '-' }}</div>
        </div>
      </div>
    </div>
    
    <!-- 信号灯区域 -->
    <div class="signal-card">
      <h2 class="card-title">
        <Volume2 class="icon" /> 摩斯密码信号
      </h2>
      
      <div class="signal-display">
        <div class="signal-light" :class="{ active: isSignalActive }"></div>
        <div class="signal-text">
          点击播放按钮查看信号灯效果
        </div>
      </div>
      
      <div class="controls">
        <button class="btn primary" @click="playMorse">
          <Volume2 class="icon" /> 播放信号
        </button>
        <button 
          class="btn secondary" 
          @click="copyResult(morseResult)"
          :disabled="!morseResult"
        >
          <Clipboard class="icon" /> 复制摩斯密码
        </button>
      </div>
    </div>
    
    <!-- 参考表 -->
    <div class="reference-card">
      <h2 class="card-title">摩斯密码参考表</h2>
      
      <div class="morse-table">
        <div v-for="(row, rowIndex) in morseTable" :key="rowIndex" class="table-row">
          <div v-for="(item, itemIndex) in row" :key="itemIndex" class="table-cell">
            <div class="char">{{ item.char }}</div>
            <div class="code">{{ item.code }}</div>
          </div>
        </div>
      </div>
    </div>
    
    <!-- 通知 -->
    <div class="notification" :class="{ show: showNotification }">
      {{ notificationMessage }}
    </div>
  </div>
</template>

<style scoped>
html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  min-height: 100vh;
}

.morse-container {
  min-height: 100vh; 
  margin: 0; 
  padding: 2rem;
  box-sizing: border-box; 
  background: linear-gradient(135deg, #000000 0%, #1a1a1a 100%); 
}

.title {
  display: flex;
  align-items: center;
  justify-content: center;
  color: #B2C4FF;
  margin-bottom: 0.5rem;
  font-size: 2.5rem;
  text-shadow: 0 0 15px rgba(178, 196, 255, 0.5);
  letter-spacing: 1px;
  position: relative;
  padding: 10px 0;
}

.title::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 50%;
  transform: translateX(-50%);
  width: 300px;
  height: 3px;
  background: linear-gradient(90deg, transparent, #AA0080, transparent);
}

.icon {
  margin-right: 0.5rem;
  filter: drop-shadow(0 0 5px rgba(178, 196, 255, 0.7));
}

.subtitle {
  text-align: center;
  color: #8a8a8a;
  margin-bottom: 2rem;
  font-size: 1.1rem;
}

.converter-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(500px, 1fr));
  gap: 1.5rem;
  margin-bottom: 2rem;
}

@media (max-width: 768px) {
  .converter-grid {
    grid-template-columns: 1fr;
  }
}

.converter-card, .signal-card, .reference-card {
  background-color: rgba(20, 20, 20, 0.8);
  padding: 1.5rem;
  border-radius: 16px;
  box-shadow: 0 8px 30px rgba(0, 0, 0, 0.6);
  margin-bottom: 1.5rem;
  border: 1px solid #333;
  transition: transform 0.3s ease, box-shadow 0.3s ease;
  backdrop-filter: blur(5px);
}

.converter-card:hover, .signal-card:hover, .reference-card:hover {
  transform: translateY(-5px);
  box-shadow: 0 12px 35px rgba(170, 0, 128, 0.3);
}

.card-title {
  display: flex;
  align-items: center;
  color: #B2C4FF;
  margin-bottom: 1.5rem;
  font-size: 1.4rem;
  border-bottom: 1px solid #AA0080;
  padding-bottom: 0.8rem;
}

.form-group {
  margin-bottom: 1rem;
}

textarea {
  width: 90%;
  padding: 1.2rem;
  background-color: rgba(30, 30, 30, 0.7);
  border: 1px solid #444;
  border-radius: 10px;
  font-size: 1.05rem;
  resize: vertical;
  min-height: 120px;
  color: #f0f0f0;
  transition: all 0.3s ease;
  box-shadow: inset 0 0 10px rgba(0, 0, 0, 0.5);
  font-family: 'Courier New', monospace;
}

textarea::placeholder {
  color: #777;
}

textarea:focus {
  outline: none;
  border-color: #B2C4FF;
  box-shadow: inset 0 0 15px rgba(178, 196, 255, 0.4),
              0 0 15px rgba(178, 196, 255, 0.3);
}

.btn-group {
  display: flex;
  gap: 0.75rem;
  margin-bottom: 1.5rem;
}

.btn {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.9rem 1.2rem;
  border: none;
  border-radius: 10px;
  font-size: 0.95rem;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
  position: relative;
  overflow: hidden;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
  z-index: 1;
}

.btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    to bottom, 
    rgba(255, 255, 255, 0.3) 0%, 
    rgba(255, 255, 255, 0.1) 50%,
    transparent 100%
  );
  z-index: -1;
  transition: opacity 0.3s ease;
}

.btn:hover::before {
  opacity: 0.8;
}

.btn.primary {
  background: linear-gradient(to bottom, #AA0080, #800060);
  color: white;
  flex: 2;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
}

.btn.primary:hover {
  background: linear-gradient(to bottom, #BB0090, #900070);
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(170, 0, 128, 0.5);
}

.btn.secondary {
  background: linear-gradient(to bottom, #6A7FCC, #4A5FA8);
  color: white;
  flex: 2;
}

.btn.secondary:hover {
  background: linear-gradient(to bottom, #7A8FDC, #5A6FB8);
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(74, 95, 168, 0.4);
}

.btn.tertiary {
  background: linear-gradient(to bottom, #444, #222);
  color: #ccc;
  flex: 1;
}

.btn.tertiary:hover {
  background: linear-gradient(to bottom, #555, #333);
  transform: translateY(-3px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4);
}

.result-box {
  background: linear-gradient(145deg, rgba(30, 30, 40, 0.7), rgba(20, 20, 30, 0.7));
  border-radius: 12px;
  padding: 1.2rem;
  border: 1px solid rgba(170, 0, 128, 0.3);
  box-shadow: inset 0 0 15px rgba(0, 0, 0, 0.4);
}

.result-box h3 {
  color: #B2C4FF;
  margin-bottom: 0.8rem;
  font-size: 1.2rem;
}

.result-content {
  font-family: 'Courier New', monospace;
  font-size: 1.15rem;
  color: #f0f0f0;
  word-break: break-all;
  line-height: 1.7;
  min-height: 1.5em;
  text-shadow: 0 0 5px rgba(178, 196, 255, 0.3);
}

.signal-card {
  text-align: center;
}

.signal-display {
  margin-bottom: 1.5rem;
}

.signal-light {
  width: 140px;
  height: 140px;
  border-radius: 50%;
  background: #1a1a1a;
  margin: 0 auto 1.5rem;
  border: 10px solid #333;
  transition: all 0.2s ease;
  position: relative;
  overflow: hidden;
  box-shadow: inset 0 0 20px rgba(0, 0, 0, 0.8),
              0 0 30px rgba(0, 0, 0, 0.6);
}

.signal-light::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  border-radius: 50%;
  background: radial-gradient(circle, transparent 40%, rgba(170, 0, 128, 0.1) 100%);
}

.signal-light.active {
  background: radial-gradient(circle, #AA0080, #800060);
  border-color: #BB0090;
  box-shadow: inset 0 0 30px rgba(170, 0, 128, 0.6),
              0 0 50px rgba(170, 0, 128, 0.8);
}

.signal-text {
  color: #8a8a8a;
  font-style: italic;
  font-size: 1.1rem;
}

.controls {
  display: flex;
  justify-content: center;
  gap: 1rem;
}

.reference-card {
  margin-top: 2rem;
}

.morse-table {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 1.2rem;
}

.table-row {
  display: contents;
}

.table-cell {
  background: rgba(30, 30, 40, 0.7);
  border: 1px solid rgba(170, 0, 128, 0.2);
  border-radius: 12px;
  padding: 1.2rem;
  text-align: center;
  transition: all 0.3s ease;
  box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
}

.table-cell:hover {
  transform: translateY(-5px);
  background: rgba(40, 30, 50, 0.8);
  border-color: #B2C4FF;
  box-shadow: 0 10px 25px rgba(178, 196, 255, 0.2);
}

.char {
  font-weight: bold;
  font-size: 1.3rem;
  color: #B2C4FF;
  margin-bottom: 0.5rem;
  text-shadow: 0 0 8px rgba(178, 196, 255, 0.5);
}

.code {
  font-family: monospace;
  font-size: 1rem;
  color: #ffffff;
  letter-spacing: 1px;
  font-weight: 100px;
}

.notification {
  position: fixed;
  top: 20px;
  right: 20px;
  background: linear-gradient(to right, #AA0080, #6A00A0);
  color: white;
  padding: 1.2rem 1.8rem;
  border-radius: 10px;
  box-shadow: 0 8px 25px rgba(170, 0, 128, 0.5);
  transform: translateX(200%);
  transition: transform 0.4s cubic-bezier(0.175, 0.885, 0.32, 1.275);
  z-index: 1000;
  font-weight: 600;
  font-size: 1.1rem;
  display: flex;
  align-items: center;
  gap: 10px;
}

.notification.show {
  transform: translateX(0);
}
</style>